package com.gxar.quick.ar.server.base.model.protocol.editor.unity;

import com.gxar.common.entity.SystemCodeEnum;
import com.gxar.common.utils.AssertUtils;
import com.gxar.quick.ar.server.base.common.constant.ArProtocolConstant;
import com.gxar.quick.ar.server.base.common.enums.protocol.*;
import com.gxar.quick.ar.server.base.model.protocol.ArQuaternion;
import com.gxar.quick.ar.server.base.model.protocol.ArSizeModel;
import com.gxar.quick.ar.server.base.model.protocol.ArVector3;
import com.gxar.quick.ar.server.base.model.protocol.CommonInputWorkInfo;
import com.gxar.quick.ar.server.base.model.protocol.common.CommonArContentModel;
import com.gxar.quick.ar.server.base.model.protocol.common.CommonArImageIdentifyModel;
import com.gxar.quick.ar.server.base.model.protocol.common.CommonArProtocol;
import com.gxar.quick.ar.server.base.model.protocol.editor.EditorArProtocol;
import lombok.Data;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Unity编辑器协议
 *
 * @author zxh
 * @version 1.0
 * @created 2024/01/02.
 */
@Data
public class UnityEditorArProtocol implements EditorArProtocol {

    /**
     * 作品编号
     */
    private String workId;

    /**
     * 制作方法
     */
    private ArProductMethodEnum productMethod;

    /**
     * 加载场景
     */
    private ArLoadSceneEnum scene;

    /**
     * 识别模型
     */
    private UnityEditorArIdentifyModel identifyModel;

    /**
     * 内容列表
     */
    private List<UnityEditorArContentModel> contentModelList;

    @Override
    public ArProtocolEditorEnum getType() {
        return ArProtocolEditorEnum.UNITY_EDITOR;
    }

    @Override
    public void fill(CommonInputWorkInfo workInfo, ArLoadSceneEnum arLoadSceneEnum) {
        this.workId = workInfo.getWorksId();
        this.scene = arLoadSceneEnum;
        this.identifyModel = UnityEditorArIdentifyModel.from(workInfo.getIdentify());
        this.contentModelList = UnityEditorArContentModel.from(workInfo.getContent());
        this.productMethod = ArProductMethodEnum.getByCode(workInfo.getProductionMethod());
    }

    @Override
    public CommonArProtocol convert2CommonProtocol() {
        AssertUtils.notNull(workId, SystemCodeEnum.SERVER_ERROR.getRet(), "workId不能为空");
        AssertUtils.notNull(productMethod, SystemCodeEnum.SERVER_ERROR.getRet(), "productMethod不能为空");
        AssertUtils.notNull(scene, SystemCodeEnum.SERVER_ERROR.getRet(), "loadScene不能为空");
        AssertUtils.notNull(identifyModel, SystemCodeEnum.SERVER_ERROR.getRet(), "identifyModel不能为空");
        AssertUtils.notNull(contentModelList, SystemCodeEnum.SERVER_ERROR.getRet(), "contentModelList不能为空");

        CommonArProtocol commonArProtocol = new CommonArProtocol();

        CommonArImageIdentifyModel commonArImageIdentifyModel = convert2CommonIdentify(identifyModel);
        commonArProtocol.setIdentifyModel(commonArImageIdentifyModel);
        commonArProtocol.setVersion(identifyModel.getVersion());
        commonArProtocol.setWorkId(workId);
        commonArProtocol.setProductMethod(productMethod);
        commonArProtocol.setEditor(getType());

        // 加载类型不同计算机制不同
        if (ArLoadSceneEnum.PREVIEW.equals(scene) || ArLoadSceneEnum.PLANE.equals(scene)) {
            commonArProtocol.setDisplayMode(ArDisplayModeEnum.PLANE);
            commonArProtocol.setSpaceBaseSize(ArProtocolConstant.PT_STABLE_VALUE);
        } else {
            commonArProtocol.setDisplayMode(ArDisplayModeEnum.MARKER); // 默认
            commonArProtocol.setSpaceBaseSize(commonArImageIdentifyModel.getWorldSize().getWidth());
        }

        List<CommonArContentModel> commonArContentModels = convert2CommonContent(contentModelList);
        commonArProtocol.setContentModelList(commonArContentModels);

        return commonArProtocol;
    }

    /**
     * Web编辑器配置转化
     *
     * @param inputModel web编辑器识别模型
     * @return 通用识别模型
     */
    private CommonArImageIdentifyModel convert2CommonIdentify(UnityEditorArIdentifyModel inputModel) {
        AssertUtils.notNull(inputModel, SystemCodeEnum.PARAM_ERROR.getRet(), "输入模型不能为空");

        CommonArImageIdentifyModel outputModel = new CommonArImageIdentifyModel();
        outputModel.setLinkUrl(inputModel.getUrl()); // TODO: 资源链接前缀

        String scale = CommonArProtocol.DEFAULT_COMMON_IDENTIFY_IMAGE_SCALE;
        outputModel.setScale(ArVector3.from(scale));

        String position = CommonArProtocol.DEFAULT_COMMON_IDENTIFY_IMAGE_POSITION;
        outputModel.setPosition(ArVector3.from(position));

        String rotation = CommonArProtocol.DEFAULT_COMMON_IDENTIFY_IMAGE_ROTATION;
        outputModel.setRotation(ArVector3.from(rotation));

        outputModel.setWorldSize(new ArSizeModel(inputModel.getSize().getWidth(), inputModel.getSize().getHeight(), 0d));
        outputModel.setOriginSize(new ArSizeModel(inputModel.getSize().getWidth(), inputModel.getSize().getHeight(), 0d));

        outputModel.setUnitFactor(inputModel.getUnitFactor());

        outputModel.setShowIdentify(false); // 默认不展示, 待定
        outputModel.setPixelPerUnit(inputModel.getPixelPerUnit());

        return outputModel;
    }

    private List<CommonArContentModel> convert2CommonContent(List<UnityEditorArContentModel> inputModels) {
        AssertUtils.notNull(inputModels, SystemCodeEnum.PARAM_ERROR.getRet(), "输入模型不能为空");
        return inputModels.stream().filter(Objects::nonNull).map(this::convert2CommonContent).collect(Collectors.toList());
    }

    /**
     * Web编辑器配置转化
     *
     * @param inputModel web编辑器内容模型
     * @return 通用内容模型
     */
    private CommonArContentModel convert2CommonContent(UnityEditorArContentModel inputModel) {
        AssertUtils.notNull(inputModel, SystemCodeEnum.PARAM_ERROR.getRet(), "输入模型不能为空");
        AssertUtils.notNull(inputModel.getScale(), SystemCodeEnum.PARAM_ERROR.getRet(), "scale不能为空");
        AssertUtils.notNull(inputModel.getPosition(), SystemCodeEnum.PARAM_ERROR.getRet(), "position不能为空");
        AssertUtils.notNull(inputModel.getQuaternion(), SystemCodeEnum.PARAM_ERROR.getRet(), "quaternion不能为空");

        CommonArContentModel outputModel = new CommonArContentModel();
        outputModel.setType(inputModel.getType().getName());

        if (Objects.nonNull(inputModel.getIsSheet()) && inputModel.getIsSheet()) {
            outputModel.setSubType(ArContentSubTypeEnum.SPRITE);
        } else {
            outputModel.setSubType(ArContentSubTypeEnum.DEFAULT); // TODO:
        }

        outputModel.setLinkUrl(inputModel.getUrl()); // TODO: 资源链接前缀
        outputModel.setId(inputModel.getUuid().toString());
        outputModel.setIs3dItem(ArUnityEditorContentTypeEnum.MODEL.equals(inputModel.getType()));
        outputModel.setFillType(ArContentFillTypeEnum.AUTO);
        outputModel.setIsBorder(false);

        if (Objects.nonNull(inputModel.getIsAlpha()) && inputModel.getIsAlpha()) {
            outputModel.setAlphaMode(ArAlphaMode.BLEND.getName());
        } else {
            outputModel.setAlphaMode("");
        }

        outputModel.setEffect(ArEffectEnum.DEFAULT);

        outputModel.setScale(ArVector3.create(inputModel.getOriginScale()));
        outputModel.setPosition(ArVector3.create(inputModel.getOriginPosition()));
        outputModel.setRotation(ArVector3.create(inputModel.getOriginRotate()));
        outputModel.setQuaternion(new ArQuaternion(inputModel.getOriginQuaternion()));

        if (Objects.nonNull(inputModel.getSize())) {
            outputModel.setWorldSize(ArSizeModel.create(inputModel.getSize()));
            outputModel.setOriginSize(ArSizeModel.create(inputModel.getSize()));
        }

        outputModel.setHasBorder(false);
        outputModel.setPixelPerUnit(inputModel.getPixelPerUnit());

        return outputModel;
    }
}
